package com.homer.gps.track.helper;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
import android.os.AsyncTask;

import com.homer.gps.track.R;
import com.homer.gps.track.helper.UsefullStaff.Dir;
import com.homer.gps.track.persist.DatabaseHelper;
import com.homer.gps.track.persist.PlaceModel;
import com.homer.gps.track.persist.Repository;
import com.homer.gps.track.persist.RouteModel;
import com.homer.gps.track.persist.StopModel;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.HeaderFooter;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;

public class TracksExporter {
	
	public enum Export {PDF, TXT}

	private Context context;
	private Font titleFont, boldFont, regularFont;
	
	private Repository repository;
	private DatabaseHelper dbHelper = null;
	
	public TracksExporter(Context context) {
		this.context = context;
		
		repository = new Repository(getHelper());

		try {
            String path;
            InputStream inputStream = context.getAssets().open("fonts/DroidSans.ttf");
            File parent = new File(UsefullStaff.getExternalStorageAppRootDir(context) + "/Fonts");
            parent.mkdirs();
            OutputStream outputStream=new FileOutputStream(path = (parent.getAbsolutePath() + "/exportFont.ttf"));
            byte buffer[]=new byte[1024];
            int length=0;

            while((length=inputStream.read(buffer))>0) {
                outputStream.write(buffer,0,length);
            }
            outputStream.close();
            inputStream.close();

            BaseFont bf = BaseFont.createFont(path, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

		    titleFont = new Font(bf, 20, Font.BOLD);
	    	boldFont = new Font(bf, 13, Font.BOLD);
            regularFont = new Font(bf, 12, Font.ITALIC);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
	
	public String exportRoute(RouteModel route, Export type) {
		AsyncTask<Object, Integer, String> aTask = new AsyncTask<Object, Integer, String>() {

			@Override
			protected String doInBackground(Object... arg) {
				RouteModel routeToExport = (RouteModel)arg[0];
				File parent = new File(UsefullStaff.getExternalStorageDir(context,Dir.EXPORT, routeToExport.getName()));
		        parent.mkdirs();
		        FileOutputStream fos;
		        String path = null;
								
				switch ((Export)arg[1]) {
	            case PDF:
	                try {
						fos = new FileOutputStream(path = (parent.getAbsolutePath() + "/" + routeToExport.getName() + "_export.pdf"));
						exportRouteToPdf(routeToExport, fos);
		                fos.close();
					} catch (FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (DocumentException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
	                
	                break;
	            case TXT:
	                try {
						fos = new FileOutputStream(path = (parent.getAbsolutePath() + "/" + routeToExport.getName() + "_export.txt"));
						BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
		                exportRouteToTxt(routeToExport, bw);
		                bw.close();
					} catch (FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (DocumentException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
	                break;
	        }
				return path;
			}
			
		};
		aTask.execute(route, type);
		String result = "";
		try {
			result = aTask.get();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	public void exportRouteToPdf(RouteModel routeToExport,FileOutputStream fos) throws DocumentException, IOException{
		Document document = new Document(PageSize.A4, 36, 36, 54, 36);
		try {
			PdfWriter.getInstance(document, fos);
			
			Bitmap logoBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.track_launcher);
			ByteArrayOutputStream stream = new ByteArrayOutputStream();
			logoBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
			Image logo = Image.getInstance(stream.toByteArray());
			logo.setAlignment(Image.MIDDLE);
			logo.scalePercent((100f/logo.getWidth())*30f);
			Chunk chunk = new Chunk(logo, 5, -8);
			CustomFontPhrase phrase = new CustomFontPhrase(context.getString(R.string.powered_by));
			phrase.add(chunk);
			HeaderFooter footer = new HeaderFooter(phrase, false);
			footer.setAlignment(Element.ALIGN_RIGHT);
			footer.setBorder(Rectangle.NO_BORDER);
			document.setFooter(footer);
			document.open();
			document.addTitle(context.getString(R.string.yes));
			
			PdfPTable table = new PdfPTable(3);
			table.setWidthPercentage(100f);
			PdfPCell cell;
			cell = new NoBorderPdfPCell(new CustomFontPhrase(context.getString(R.string.track_report), titleFont));
			cell.setBorder(Rectangle.NO_BORDER);
			cell.setColspan(3);
			cell.setFixedHeight(60f);
			table.addCell(cell);
			
			// date
			table.addCell(createTableRow(context.getString(R.string.generated_date), (String) UsefullStaff.getFormatedDateAndTime(new Date(), "dd/MM/yyyy")));
			
			// name
			table.addCell(createTableRow(context.getString(R.string.route_name), (String) routeToExport.getName()));
			
			// type
			table.addCell(createTableRow(context.getString(R.string.route_type), (String) UsefullStaff.getRouteTypeString(context, routeToExport.getType())));
			
			// note 
			table.addCell(createTableRow(context.getString(R.string.route_note), (String) routeToExport.getNote()));
			
			// empty lines
			addEmptyLine(table, 3, 1);
			
			// track start
			StopModel startStop = null;
			List<StopModel> stops = null;
			try {
				stops = repository.lookupStopsForRoute(routeToExport, StopModel.STOP_TYPE_START);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			startStop = stops.get(0);
			
			if (startStop != null) {
				cell = createTableRow(context.getString(R.string.start_place), (String) UsefullStaff.getFormatedDateAndTime(startStop.getStartDateTime(), "dd/MM/yyyy"));
				cell.setBorder(Rectangle.BOTTOM);
				cell.setBorderWidth(1.5f);
				cell.setPaddingBottom(5f);
				cell.setVerticalAlignment(Element.ALIGN_CENTER);
				cell.setColspan(3);
				table.addCell(cell);
				
				PlaceModel startPlace = null;
				try {
					startPlace = repository.lookupPlacesForStop(startStop);
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				if (startPlace != null) {
					
					// place name
					table.addCell(createTableRow(context.getString(R.string.place_name), (String) startPlace.getName()));
					
					// place type
					table.addCell(createTableRow(context.getString(R.string.route_type), (String) UsefullStaff.getPlaceTypeString(context, startPlace.getType())));
					
					// place address
			        table.addCell(createTableRow(context.getString(R.string.place_address), (String) startPlace.getParsedAddress()));
					
					//image
					PdfPTable attachmentTable = new PdfPTable(2);

					String name = ImageHelper.getImageNameNoExtensionFromImagePath(startPlace.getImagePath());
					String date = new ExifInterface(startPlace.getImagePath()).getAttribute(ExifInterface.TAG_DATETIME);

					Image image = Image.getInstance(startPlace.getImagePath());
					image.scalePercent((200f/image.getWidth())*100f);

					cell = new NoBorderPdfPCell(image, true);
					cell.setVerticalAlignment(Element.ALIGN_CENTER);
					cell.setPaddingRight(10f);
					cell.setRowspan(2);
					cell.setColspan(1);
					attachmentTable.addCell(cell);

					cell = new NoBorderPdfPCell(new CustomFontPhrase(context.getString(R.string.picture_name) + " " + name));
					cell.setColspan(1);
					attachmentTable.addCell(cell);

					cell = new NoBorderPdfPCell(new CustomFontPhrase(context.getString(R.string.created) + " " + date));
					cell.setColspan(1);
					attachmentTable.addCell(cell);

					addEmptyLine(table, 3, 1);
					cell = new NoBorderPdfPCell(attachmentTable);
					cell.setColspan(3);
					table.addCell(cell);
				}
				
				
			}
			document.add(table);
		} catch (DocumentException de) {
			System.err.println(de.getMessage());
		}

		document.close();
	}
	
	private PdfPCell createTableRow(String title, String value){
		PdfPCell cell;
		PdfPTable table = new PdfPTable(5);
		cell = new NoBorderPdfPCell(new CustomFontPhrase(title + ": ", boldFont));
		cell.setColspan(1);
		table.addCell(cell);
		cell = new NoBorderPdfPCell(new CustomFontPhrase(value == null? "" : value));
		cell.setColspan(4);
		table.addCell(cell);
        cell = new NoBorderPdfPCell(table);
        cell.setColspan(3);
		return cell;
	}
	
	public void exportRouteToTxt(RouteModel routeToExport,BufferedWriter bw) throws DocumentException, IOException{
		newLines(bw, 2);
        writeText(bw, context.getString(R.string.track_report));
        newLines(bw, 2);

        // date
        writeText(bw, context.getString(R.string.generated_date) + ": " + (String) UsefullStaff.getFormatedDateAndTime(new Date(), "dd/MM/yyyy"));

        // name
        writeText(bw, context.getString(R.string.route_name) + ": " + routeToExport.getName());

        // type
        writeText(bw, context.getString(R.string.route_type) + ": " + (String) UsefullStaff.getRouteTypeString(context, routeToExport.getType()));

        // note 
        writeText(bw, context.getString(R.string.route_note) + ": " + (String) routeToExport.getNote());
        newLines(bw, 1);

	}
	
	private void writeText(BufferedWriter bw, String text) throws IOException {
        bw.write(text);
        bw.newLine();
    }
	
	private void newLines(BufferedWriter bw, int count) throws IOException {
        for (int i=0; i<count; i++)
            bw.newLine();
    }
	
	private void addEmptyLine(PdfPTable table, int colspan, int number) {
		for (int i = 0; i < number; i++) {
			PdfPCell cell = new NoBorderPdfPCell(new CustomFontPhrase(" "));
			cell.setColspan(colspan);
			table.addCell(cell);
		}
	}
	
	private DatabaseHelper getHelper() {
		if (dbHelper == null) {
			dbHelper = (DatabaseHelper)OpenHelperManager.getHelper(context, DatabaseHelper.class);
		}
		return dbHelper;
	}
	
	private class NoBorderPdfPCell extends PdfPCell {

		public NoBorderPdfPCell() {
			super();
			setBorder(Rectangle.NO_BORDER);
		}

		public NoBorderPdfPCell(Image image) {
			super(image);
			setBorder(Rectangle.NO_BORDER);
		}

		public NoBorderPdfPCell(PdfPCell cell) {
			super(cell);
			setBorder(Rectangle.NO_BORDER);
		}

		public NoBorderPdfPCell(PdfPTable table) {
			super(table);
			setBorder(Rectangle.NO_BORDER);
		}

		public NoBorderPdfPCell(Phrase phrase) {
			super(phrase);
			setBorder(Rectangle.NO_BORDER);
		}

		public NoBorderPdfPCell(Image image, boolean fit) {
			super(image, fit);
			setBorder(Rectangle.NO_BORDER);
		}

		public NoBorderPdfPCell(PdfPTable table, PdfPCell style) {
			super(table, style);
			setBorder(Rectangle.NO_BORDER);
		}
	}
	
	private class CustomFontPhrase extends Phrase{
        public CustomFontPhrase(String string, Font font) {
            super(string, font);
        }

        public CustomFontPhrase(String string) {
            super(string, regularFont);
        }
    }
}